package py.com.alfa.escriba.gui.controller;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.context.WebApplicationContext;
import org.thymeleaf.TemplateEngine;
import org.winter.dialect.response.JsonResponse;
import org.winter.utils.command.AjaxResponse;
import org.winter.utils.command.ControllerObject;

import py.com.alfa.escriba.gui.controller.object.gestion.VehiculosControllerObject;
import py.com.alfa.escriba.gui.controller.view.View;
import py.com.alfa.escriba.gui.controller.view.ViewManager;
import py.com.alfa.escriba.gui.dto.admin.TabRefDTO;
import py.com.alfa.escriba.gui.dto.gestion.DatoscomplementariosDTO;
import py.com.alfa.escriba.gui.dto.gestion.VehiculosDTO;
import py.com.alfa.escriba.gui.dto.gestion.VehiculosinfoDTO;
import py.com.alfa.escriba.gui.rest.services.DatosComplService;
import py.com.alfa.escriba.gui.rest.services.TemplatesService;
import py.com.alfa.escriba.gui.rest.services.VehiculosService;
import py.com.alfa.escriba.gui.services.HelperService;
import py.com.alfa.escriba.gui.services.TabRef;
import py.com.alfa.escriba.gui.session.SystemInfo;
import py.com.alfa.escriba.gui.spring.processors.SpringBean;
import py.com.alfa.escriba.gui.utils.ObjectUtils;
import py.com.sif.rest.client.spring.exception.RestClientException;

@Controller
@Scope("session")
@SessionAttributes("vehiculos")
@RequestMapping("/vehiculos")
public class VehiculosController implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -3807025844096914070L;
	private final static String PAGE_NAME = "pag:vehiculos";
	private final static String CONTROLLER_OBJECT_NAME = "vehiculos";
	
	private Logger log = LoggerFactory.getLogger(getClass());
	@SpringBean private SystemInfo systemInfo;
	@SpringBean private ViewManager viewManager;
	@SpringBean private VehiculosService vehiculosService;
	@SpringBean private HelperService helperService;
	@SpringBean private TemplatesService templatesService;
	@SpringBean private DatosComplService datosComplService;
	
	@Autowired
	private WebApplicationContext wac;
	
	@Autowired
	private TemplateEngine templateEngine;
	@ControllerObject	
	private VehiculosControllerObject vehiculos;
	private Locale locale;
	
	
	public VehiculosController() {
		this.loadObjects();
	}

	private void loadObjects() {
		setLocale(LocaleContextHolder.getLocale());
	}

	private String verifAuto() {
		Subject subject = SecurityUtils.getSubject();
		if (subject == null || !subject.isAuthenticated()) {
			return "redirect:/";
		}		
		Boolean permitted = subject.isPermitted(VehiculosController.PAGE_NAME);
		systemInfo.setSystemError(false);
		if (!permitted) {
			systemInfo.setSystemError(true);
			systemInfo.setErrorMessage("El usuario no esta autorizado para utilizar este recurso");
			return "error";
		}
		return null;
	}

	
	@ModelAttribute(CONTROLLER_OBJECT_NAME)
	public VehiculosControllerObject getVehiculos() {
		return this.vehiculos;
	}

	public void setVehiculos(VehiculosControllerObject listas) {
		this.vehiculos = listas;
	}

	public Locale getLocale() {
		return locale;
	}

	public void setLocale(Locale locale) {
		this.locale = locale;
	}
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String homePage(Model model, HttpServletRequest request, HttpServletResponse response) {
		this.log.info("vehiculos!");
		try {
			this.getVehiculos().view().disableAll();
			String auto = this.verifAuto();
			if ( auto != null ) {
				return auto;
			}
			loadObject();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
		}
		return View.VEHICULOS;
	}
	
	private void loadObject(){
		try {
			this.getVehiculos().setTemplates(this.templatesService.listTemplatesByIdTipo(29L));
			this.getVehiculos().setDatosComplementarios(this.datosComplService.listDatoscomplementarios());
			this.getVehiculos().setPaises(this.helperService.getPaises());
			this.getVehiculos().setMonedas(this.helperService.getMonedas());
			this.getVehiculos().setUsos(this.helperService.getTablaRef(TabRef.USO_VEHICULO));
			this.getVehiculos().setEstados(this.helperService.getTablaRef(TabRef.ESTADO_VEHICULO));
			this.getVehiculos().setVehiculos(this.vehiculosService.listVehiculos());
			this.getVehiculos().setValores(new ArrayList<TabRefDTO>());
			this.getVehiculos().view().enable().lista();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
		}
	}

	@RequestMapping(value = "/agregarVehiculo", method = RequestMethod.POST)
	public @ResponseBody JsonResponse agregarVehiculo(Model model, HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.VEHICULOS) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult) {
		this.log.info("vehiculos - Nuevo!");
		
		try {
			this.getVehiculos().setVehiculoOri(null);
			this.getVehiculos().setVehiculo(new VehiculosDTO());
			this.getVehiculos().setVehiculoInfo(new VehiculosinfoDTO());
			this.getVehiculos().getVehiculoInfo().setDatoComplementario(this.getVehiculos().getDatosComplementarios().get(0));
			this.getVehiculos().getVehiculo().setVehiculosInfo(this.vehiculosService.listDatosVehiculosInfo());
			this.getVehiculos().getVehiculo().setActivo(true);
			this.getVehiculos().getVehiculo().setPais(this.helperService.getPaisByCodigo("PRY"));
			this.getVehiculos().getVehiculo().setMoneda(this.helperService.getMonedasByCodigo("DOL"));
			this.getVehiculos().getVehiculo().setUso(this.helperService.getTablaRef(TabRef.USO_VEHICULO, TabRef.USO_PARTICULAR));
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
			return jResponse.error(e.getMessage());
		}
		
		this.getVehiculos().view().disableAll().enable().vehiculo();
		return jResponse.success(request, response, wac, model, templateEngine);
	}	

	@RequestMapping(value = "/consultar", method = RequestMethod.POST)
	public @ResponseBody JsonResponse consultar(Model model, HttpServletRequest request, HttpServletResponse response, 
		@AjaxResponse(View.VEHICULO) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult) {
		this.log.info("vehiculos - consultar! {}");
		try {
			this.getVehiculos().setVehiculos(this.vehiculosService.buscarVehiculos(this.getVehiculos().getFiltros()));
			this.getVehiculos().view().disableAll().enable().lista();
			jResponse.setView(View.VEHICULOS);
			} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/cancelar/{operacion}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse cancelar(Model model, HttpServletRequest request, HttpServletResponse response, 
		@AjaxResponse(View.VEHICULO) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult, 
		@PathVariable("operacion") String operacion) {
		this.log.info("vehiculos - cancelar! {}", operacion);
		
		try {
			if ( operacion == null ) {
				return jResponse.error("Debe informar la operacion a cancelar");
			}
			if ( "VEHICULO".equals(operacion)) {
				if ( this.getVehiculos().getVehiculoOri() != null) {
					this.getVehiculos().getVehiculos().add(this.getVehiculos().getVehiculoOri());
				}
				this.getVehiculos().setVehiculoOri(null);
			    this.getVehiculos().setVehiculo(null);
			    this.getVehiculos().view().disableAll().enable().lista();
			    jResponse.setView(View.VEHICULOS);
			}			
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	
	@RequestMapping(value = "/guardarVehiculoInfo", method = RequestMethod.POST)
	public @ResponseBody JsonResponse guardarVehiculosinfo(Model model, HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.VEHICULO) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult){
		
		this.log.info("GUARDAR VEHICULO INFO!");
		try {
			// Verifico que se hayan cargado todos los valores
			VehiculosinfoDTO vinfo = this.getVehiculos().getVehiculoInfo();
			if ( ObjectUtils.isEmpty(vinfo) ) {
				return jResponse.error("Debe informar informacion del vehiculo");
			}
			
			DatoscomplementariosDTO dc = vinfo.getDatoComplementario();
			if ( ObjectUtils.isEmpty(dc) ) {
				return jResponse.error("Debe informar el tipo de dato");
			}
			
			Long idDato = vinfo.getDatoComplementario().getId();
			dc = this.datosComplService.showDatoscomplementarios(idDato);
			this.log.info("DATO COMPLEMENTARIO : {}!", dc);
			
			TabRefDTO tipoDato = dc.getTipoDato();
			this.log.info("TIPO DE DATO : {}!", tipoDato);
			if (tipoDato.getCodigo().equals("INTEGER")){
				if (vinfo.getValorInteger() == null) {
					return jResponse.error("Debe informar el valor");
				}
				vinfo.setValor(String.valueOf(vinfo.getValorInteger()));
			}
			if (tipoDato.getCodigo().equals("STRING")){
				if ( ObjectUtils.isEmpty(vinfo.getValor()) ) {
					return jResponse.error("Debe informar el valor");
				}
			}
			if (tipoDato.getCodigo().equals("DATE")){
				if (vinfo.getValorDate() == null) {
					return jResponse.error("Debe informar el valor");
				}
				SimpleDateFormat sdf= new SimpleDateFormat(dc.getMascara());
				vinfo.setValor(sdf.format(vinfo.getValorDate()));
			}
            
			if(this.getVehiculos().getVehiculo().getVehiculosInfo() == null){
				this.getVehiculos().getVehiculo().setVehiculosInfo(new ArrayList<VehiculosinfoDTO>());
			}else{
				for (VehiculosinfoDTO info : this.getVehiculos().getVehiculo().getVehiculosInfo()) {
					if(info.getIddato().equals(this.getVehiculos().getVehiculoInfo().getIddato())){
						return jResponse.error("Ya se informo el tipo de dato que se quiere dar de alta");
					}
				}
			}
			
			this.getVehiculos().getVehiculo().getVehiculosInfo().add(this.getVehiculos().getVehiculoInfo());
			this.getVehiculos().setVehiculoInfo(new VehiculosinfoDTO());
			this.getVehiculos().getVehiculoInfo().setDatoComplementario(dc);
			DatoscomplementariosDTO dato = this.getVehiculos().getVehiculoInfo().getDatoComplementario();
			this.log.info("DATO : {}", dato);
			
			this.getVehiculos().view().disableAll().enable().vehiculo();
			
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
	    
	    return jResponse.success(request, response, wac, model, templateEngine);
	  }		

	@RequestMapping(value = "/deleteVehiculoInfo/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse deleteVehiculosinfo(Model model,HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.VEHICULO) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult, 
		         @PathVariable("index") String ind) {
		this.log.info("\n==============\nELIMINANDO VEHICULO INFO! {}\n==============\n", ind);
		try {
			Integer index = Integer.parseInt(ind);
			VehiculosinfoDTO obj = this.getVehiculos().getVehiculo().getVehiculosInfo().get(index);
			this.log.info("Vehiculo info: {}", obj);
			
			if(this.getVehiculos().getVehiculo().getEliminadosVehiculosInfo() == null){
				this.getVehiculos().getVehiculo().setEliminadosVehiculosInfo(new ArrayList<Long>());
			}
			
			this.getVehiculos().getVehiculo().getEliminadosVehiculosInfo().add(obj.getId());
			this.getVehiculos().getVehiculo().getVehiculosInfo().remove(obj);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/guardarVehiculo", method = RequestMethod.POST)
	public @ResponseBody JsonResponse guardarVehiculo(Model model, HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.VEHICULO) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult){
		this.log.info("GUARDAR VEHICULO!");
		try {
			
			VehiculosDTO obj = this.getVehiculos().getVehiculo();	    	
			/*for (VehiculosDTO dto : this.getVehiculos().getVehiculos()) {
				if ( dto.getChapa()!=null && obj.getChapa()!=null && dto.getChapa().equals(obj.getChapa())) {
					return jResponse.error("Ya existe la chapa que se quiere dar de alta");		
				}
			}*/
			
			if ( CollectionUtils.isEmpty(obj.getVehiculosInfo()) ) {
				return jResponse.error("Debe informar al menos una informacion del vehiculo");
			}
			
			this.log.info("VEHICULO:{}", obj);
			
			if ( obj.getId() == null ) {
				this.vehiculosService.createVehiculo(obj);
			} else {
				this.vehiculosService.saveVehiculo(obj);
			}
			this.getVehiculos().setVehiculos(this.vehiculosService.listVehiculos());
			this.getVehiculos().setVehiculo(null);
			this.getVehiculos().setVehiculoOri(null);
			this.getVehiculos().view().disableAll().enable().lista();
			jResponse.setView(View.VEHICULOS);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
			return jResponse.error(e.getMessage());
		}
		
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	

	@RequestMapping(value = "/editarVehiculo/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse editarVehiculo(Model model,HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.VEHICULOS) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult, 
		         @PathVariable("index") String ind) {
		this.log.info("\n============== EDITAR VEHICULO! {}\n==============\n", ind);
		try {
			Integer index = Integer.parseInt(ind);
			VehiculosDTO obj = this.getVehiculos().getVehiculos().get(index);
			this.log.info("VEHICULO: {}", obj);
			VehiculosDTO vehiculo = this.vehiculosService.showVehiculo(obj.getId());
			vehiculo.setEstado(this.helperService.getTablaRef(TabRef.ESTADO_VEHICULO, vehiculo.getIdestadovehiculo()));
			vehiculo.setUso(this.helperService.getTablaRef(TabRef.USO_VEHICULO, vehiculo.getIduso()));
			vehiculo.setPais(this.helperService.getPaisById(vehiculo.getIdpaisvehiculo()));
			vehiculo.setMoneda(this.helperService.getMonedasById(vehiculo.getId()));
			if(vehiculo.getIdtemplatecertificado() != null){
				vehiculo.setTemplate(this.templatesService.showTemplates(vehiculo.getIdtemplatecertificado()));
			}
			this.getVehiculos().setVehiculo(vehiculo);		
			this.getVehiculos().setVehiculoOri(new VehiculosDTO());
			this.getVehiculos().setVehiculoInfo(new VehiculosinfoDTO());
			this.getVehiculos().getVehiculoInfo().setDatoComplementario(this.getVehiculos().getDatosComplementarios().get(0));
//			this.getVehiculos().getVehiculo().setVehiculosInfo(vehiculo.getVehiculosInfo());
			ObjectUtils.copyValues(vehiculo, this.getVehiculos().getVehiculoOri());
			this.getVehiculos().getVehiculos().remove(obj);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		this.getVehiculos().view().disableAll().enable().vehiculo();
//		jResponse.setView(View.VEHICULO);
		return jResponse.success(request, response, wac, model, templateEngine);
	}

	@RequestMapping(value = "/deleteVehiculo/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse deleteVehiculo(Model model,HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.VEHICULOS) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult, 
		         @PathVariable("index") String ind) {
		this.log.info("\n==============\nELIMINANDO DIRECCION! {}\n==============\n", ind);
		try {
			Integer index = Integer.parseInt(ind);
			VehiculosDTO obj = this.getVehiculos().getVehiculos().get(index);
			this.log.info("VEHICULO: {}", obj);
			if ( obj.getId() != null ) {
				this.vehiculosService.deleteVehiculo(obj.getId());
			}
			this.getVehiculos().getVehiculos().remove(obj);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/selectDatoEvent", method = RequestMethod.POST)
	public @ResponseBody JsonResponse selectDatoEvent(Model model, HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.VEHICULO) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) VehiculosControllerObject vehiculos, BindingResult bindingResult){
		this.log.info("SELECT DATO VEHICULO!");
		try {
			Long idDato = null;
			if(this.getVehiculos().getVehiculoInfo().getDatoComplementario() != null)
				idDato = this.getVehiculos().getVehiculoInfo().getDatoComplementario().getId();
			
			this.getVehiculos().getVehiculoInfo().setDatoComplementario(this.datosComplService.showDatoscomplementarios(idDato));
			DatoscomplementariosDTO dato = this.getVehiculos().getVehiculoInfo().getDatoComplementario();
			this.log.info("DATO : {}", dato);
			
			if(dato.getUsaListaDeValores()){
				this.getVehiculos().setValores(this.helperService.getTablaRef(dato.getListadevalor()));
			}else{
				this.getVehiculos().getVehiculoInfo().setValorRef(null);
				this.getVehiculos().setValores(new ArrayList<TabRefDTO>());
			}
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
}	

